package cn.takovh.zpl;

import cn.takovh.zpl.bean.Head;
import cn.takovh.zpl.bean.Media;
import cn.takovh.zpl.bean.PlayListItem;
import javafx.collections.ObservableList;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.TagException;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Service {


    private ZPL getZpl(File file) throws DocumentException {
        Document document = Utils.parse(file);
        return ZPL.parse(document);
    }

    public ZPL loadZPL() throws DocumentException {

        FileChooser fileChooser = new FileChooser();
        //设置标题
        fileChooser.setTitle("单选文件");
        //设置打开初始地址
        fileChooser.setInitialDirectory(Utils.initialDirectory);
        //过滤选择文件类型
        fileChooser.getExtensionFilters().add(Utils.zplExtensionFilter);
        //显示选择窗口,获取选中文件
        List<File> list = fileChooser.showOpenMultipleDialog(new Stage());
        if (list == null) {
            return null;
        }
        File file = list.get(0);
        return getZpl(file);
    }

    public void saveZPL(String title, List<Media> mediaList) {
        ZPL zpl = new ZPL(title, mediaList);
        Document document = zpl.getDocument();

        FileChooser fileChooser = new FileChooser();
        //设置标题
        fileChooser.setTitle("保存文件");
        //设置打开初始地址
        fileChooser.setInitialDirectory(Utils.initialDirectory);
        //过滤选择文件类型
        fileChooser.getExtensionFilters().add(Utils.zplExtensionFilter);
        fileChooser.setInitialFileName(title);
        //显示选择窗口,获取选中文件
        File file = fileChooser.showSaveDialog(new Stage());
        if (file == null) return;
        try {
            Utils.writeFile(document, file);
//            XMLUtils.writeConsole(document);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void createZPL() {

    }

    public List<PlayListItem> addMedias() {
        FileChooser fileChooser = new FileChooser();
        //设置标题
        fileChooser.setTitle("多选文件");
        //设置打开初始地址
        fileChooser.setInitialDirectory(Utils.initialDirectory);
        //过滤选择文件类型
        fileChooser.getExtensionFilters().add(Utils.musicExtensionFilter);
        //显示选择窗口,获取选中文件
        List<File> list = fileChooser.showOpenMultipleDialog(new Stage());
        return getPlayList(list);
    }

    public List<PlayListItem> addFolder(TextField title) {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        //设置标题
        directoryChooser.setTitle("选择文件夹");
        //设置打开初始地址
        directoryChooser.setInitialDirectory(Utils.initialDirectory);
        File file = directoryChooser.showDialog(new Stage());
        title.setText(file.getName());
        List<File> list = Utils.listMusicFiles(file);
        return getPlayList(list);
    }

    private List<PlayListItem> getPlayList(List<File> list) {
        List<Media> mediaList = new ArrayList<>();
        if (list == null) {
            return new ArrayList<>();
        }
        for (File file : list) {
            try {
                Media media = audioFileToMedia(file);
                mediaList.add(media);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        return toPlayList(mediaList);
    }

    public List<PlayListItem> toPlayList(List<Media> mediaList) {
        return mediaList
                .stream()
//                .filter(media -> Utils.stringNotEmpty(media.getSrc()))
                .map(PlayListItem::new)
                .collect(Collectors.toList());
    }

    private Media audioFileToMedia(File file) throws ReadOnlyFileException, CannotReadException, TagException, InvalidAudioFrameException, IOException {
        AudioFile audioFile = AudioFileIO.read(file);
        MP3AudioHeader audioHeader = new MP3AudioHeader(file);
        String absolutePath = file.getAbsolutePath();
        String fileName = file.getName();
        fileName = fileName.substring(0, fileName.lastIndexOf("."));
        String albumTitle = audioFile.getTag().getFirst(FieldKey.ALBUM);
        if (Utils.stringIsEmpty(albumTitle)) albumTitle = "未知专辑";
        String albumArtist = audioFile.getTag().getFirst(FieldKey.ALBUM_ARTISTS);
        if (Utils.stringIsEmpty(albumArtist)) albumArtist = "未知艺术家";
        String trackTitle = audioFile.getTag().getFirst(FieldKey.TITLE);
        if (Utils.stringIsEmpty(trackTitle)) trackTitle = fileName;
        String trackArtist = audioFile.getTag().getFirst(FieldKey.ARTIST);
        if (Utils.stringIsEmpty(trackArtist)) trackArtist = "未知艺术家";
        int trackLength = audioHeader.getTrackLength();
        return new Media(absolutePath, albumTitle, albumArtist, trackTitle, trackArtist, trackLength * 1000);
    }

    public String millisecondToTime(String millisecond) {
        return LocalTime.ofSecondOfDay(
                Long.parseLong(millisecond) / 1000
        ).format(DateTimeFormatter.ISO_TIME);
    }

    public String millisecondToTime(long millisecond) {
        return LocalTime.ofSecondOfDay(
                millisecond / 1000
        ).format(DateTimeFormatter.ISO_TIME);
    }

    public long timeToMillisecond(String time) {
        LocalTime localTime = LocalTime.parse(time, DateTimeFormatter.ISO_TIME);
        return localTime.toSecondOfDay() * 1000;
    }

    public void open(ObservableList<PlayListItem> tableItems, TextField title) throws DocumentException {
        ZPL zpl = loadZPL();
        if (zpl == null) {
            return;
        }
        Head head = zpl.getSmil().getHead();
        String ti = head.getTitle().getText();
        title.setText(ti);
        List<Media> mediaList = zpl.getSmil().getBody().getSeq().getMediaList();
        List<PlayListItem> playListItems = toPlayList(mediaList);

        tableItems.addAll(playListItems);
    }
}
